package com.dingding.common.core.base.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.transform.Transformers;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.dao.IBaseDao;
import com.dingding.common.core.util.AddScalar;
import com.dingding.common.core.util.ToolUtil;

/**
 * 
 * @ClassName: BaseDaoImpl
 * @Description:dao公共实现类，所有dao继承此类。当前类的所有异常监控放在service完成
 * @author CHEHUANBO
 * @date 2015-7-3 下午03:35:14
 * @version V1.8
 * @since V1.8
 * 
 * 此方法从V2.4.0 以后将不再建议使用
 * 
 * 
 * 
 */
@SuppressWarnings("all")
@Component("baseDao")
@Deprecated
public abstract class BaseDaoImpl<T> implements IBaseDao<T> {

	protected Logger log = Logger.getLogger(this.getClass());

	private Class<T> clazz = null;
	private final String QUERY_HQL = " FROM " + this.getGenericType().getName() + " as obj ";

	@Resource(name = "hibernateTemplate")
	private HibernateTemplate template = null;

	/**
	 * @Title: getGentricType @Description: 获取参数类型 @return Class
	 *         <T> 通过参数类型获取到的对象类型 @throws
	 */
	public Class<T> getGenericType() {

		if (this.clazz == null) {
			this.clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		}

		return clazz;

	}

	/**
	 * 
	 * @Title: getQuery @Description: 获取Query @param hql @return Query @throws
	 * 
	 */
	protected Query getQuery(String hql) {
		return this.getSession().createQuery(hql);
	}

	/**
	 * 
	 * @Title: getSession @Description: 获取session @return Session @throws
	 * 
	 */
	public Session getSession() {
		return template.getSessionFactory().getCurrentSession();
	}

	/**
	 * 
	 * @Title: getById @Description: 根据ID获取实体对象 @param id 主键ID @param isCache
	 *         是否使用查询缓存 true:是 false：不是 @return T @throws
	 * 
	 */
	@Override
	public T getById(String id) {
		T t = this.getTemplate().get(this.getGenericType(), id);
		return t;
	}

	/**
	 * 
	 * @Title: getById @Description: 根据ID获取实体对象 @param id 主键ID @param isCache
	 *         是否使用查询缓存 true:是 false：不是 @return T @throws
	 * 
	 */
	@Override
	public T getById(Integer id) {
		T t = this.getTemplate().get(this.getGenericType(), id);
		return t;
	}

	public <M> M getById2(Integer id, Class<M> clazz) {
		M m = this.getTemplate().get(clazz, id);
		return m;
	}

	/**
	 * 
	 * @Title: saveOrUpdate @Description: 保存或更新一个Hibernate对象 @param t
	 *         待保存的对象 @return void @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public void saveOrUpdate(T t) {
		this.getTemplate().saveOrUpdate(t);
	}

	/**
	 *
	 * @Title: save @Description:保存一个对象 @param t 待保存的对象 @author
	 *         CHEHUANBO @throws
	 * 
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void save(T t) {
		this.getTemplate().save(t);
	}

	/**
	 * 
	 * @Title: update @Description: 更新 @param 待保存的对象 @return void @author
	 *         CHEHUANBO @throws
	 * 
	 */
	@Override
	public void update(T t) {
		this.getTemplate().update(t);
	}

	/**
	 * 
	 * @Title: delete @Description: 删除一个hibernate对象 @param t 待删除的对象 @return
	 *         void @author CHEHUANBO @throws
	 *
	 */
	@Override
	public void delete(T t) {
		this.getTemplate().delete(t);
	}

	/**
	 * 
	 * @Title: deleteRow @Description: 根据ID删除数据，并返回受影响行数 @param hql @param id
	 *         主键ID @return int 受影响行数 @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public int deleteRow(String hql, String id) {
		Query query = this.getSession().createQuery(hql);
		int row = query.executeUpdate();
		return row;
	}

	/**
	 * 
	 * @Title: queryAll @Description: 查询表中所有数据对象 @return List
	 *         <T> 查询到的数据集合 @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public List<T> queryAll() {
		Query query = this.getSession().createQuery(this.QUERY_HQL);
		List<T> list = query.list();
		return list;
	}

	/**
	 * 
	 * @Title: queryCriteriaList @Description: 根据条件查询数据 @param criterion
	 *         查询条件 @return List<T> 查询到的数据集合 @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public List<T> queryCriteriaList(Criterion criterion) {
		Criteria criteria = this.getSession().createCriteria(this.getGenericType());
		List<T> list = criteria.add(criterion).list();
		return list;
	}

	/**
	 * @Description:根据条件查询数据
	 * @author fengshuonan
	 * @return List<T>
	 */
	@Override
	public List<T> queryCriteriaListByOrder(Criterion criterion, Order order) {
		Criteria criteria = this.getSession().createCriteria(this.getGenericType());
		List<T> list = criteria.add(criterion).addOrder(order).list();
		return list;
	}

	/**
	 * @Title: queryCriteriaList
	 * @Description: 根据条件查询数据
	 * @param criterion
	 *            查询条件
	 * @param isCache
	 *            是否使用查询缓存 true:使用 false：不使用
	 * @return List<T>查询到的数据集合
	 */
	@Override
	public List<T> queryCriteriaListByOrderDesc(Criterion criterion, String orderString, boolean isCache) {
		Criteria criteria = this.getSession().createCriteria(this.getGenericType());

		criteria.addOrder(Order.desc(orderString));

		if (isCache) {
			criteria.setCacheable(true);
		}
		List<T> list = criteria.add(criterion).list();
		return list;
	}

	/**
	 * 
	 * @Title: listHqlUnResult @Description: 根据条件查询唯一对象 @param criteria
	 *         查询条件 @return T 查询到的Hibernate实体对象 @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public T queryCriteriaUnResult(Criterion criterion) {
		Criteria criteria = this.getSession().createCriteria(this.getGenericType());
		T t = (T) criteria.add(criterion).uniqueResult();
		return t;
	}

	/**
	 * 
	 * @Title: listHql @Description: Hql带参查询 @param Hql 自定义Hql @param parm
	 *         参数值 @return List<T> 查询到的数据集合 @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public List<T> listHql(String Hql, Object... parm) {

		Query query = this.getQuery(Hql);

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(query, parm); // 设置hql参数
		}

		List<T> list = query.list();

		return list;
	}

	/**
	 * @Title: listHqlFreeObject 
	 * @Description: Sql带参查询 
	 * @param Sql 自定义Sql 
	 * @param parm 参数值
	 * @return List<T> 查询到的数据集合 
	 * @author fengshuonan 
	 */
	@Override
	public List<?> listSqlFreeObject(String sql, Class<?> clazz, Object... parm) {

		Query query = this.getSQlQuery(sql).setResultTransformer(Transformers.aliasToBean(clazz));

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(query, parm); // 设置hql参数
		}

		List list = query.list();

		return list;
	}

	/**
	 * 
	 * @Title: listHqlByPage @Description: Hql带参分页查询 @param Hql 自定义Hql @param
	 *         currentPage 当前页 @param pageSize 每页显示记录数 @param parm 查询参数 @return
	 *         List<T> 查询到的数据集合 @author CHEHUANBO @throws
	 * 
	 */
	@Override
	public List<T> listHqlByPage(String Hql, int currentPage, int pageSize, Object... parm) {

		Query query = this.getQuery(Hql);

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(query, parm); // 设置hql参数
		}

		if (pageSize != 0 && currentPage != 0) {
			query.setMaxResults(pageSize); // 每页查询多少条记录
			query.setFirstResult((currentPage - 1) * pageSize); // 从第几条记录开始查询
		}

		List<T> list = query.list();

		return list;
	}

	/**
	 * 
	 * @Title: listSqlObj @Description: 原生sql查询，返回的是Obj数组 @param sql
	 *         自定义sql @param parm 查询参数 @return List<Object[]> 查询到的数据集合 @author
	 *         CHEHUANBO @throws
	 * 
	 */
	@Override
	public List<Object[]> listSqlObj(String sql, Object... parm) {

		SQLQuery query = this.getSQlQuery(sql);

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(query, parm); // 设置sql参数
		}
		List<Object[]> list = query.list();
		return list;
	}

	/**
	 * 
	 * @Title: listSqlObjByPage @Description: 原生sql分页查询，返回的是Obj数组 @param sql
	 *         自定义sql @param parm 查询参数 @return List<Object[]> 查询到的数据集合 @author
	 *         CHEHUANBO @throws
	 * 
	 */
	@Override
	public List<Object[]> listSqlObjByPage(String sql, int currentPage, int pageSize, Object... parm) {

		SQLQuery query = this.getSQlQuery(sql);

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(query, parm); // 设置sql参数
		}

		if (pageSize != 0 && currentPage != 0) {
			query.setMaxResults(pageSize); // 每页查询多少条记录
			query.setFirstResult((currentPage - 1) * pageSize); // 从第几条记录开始查询
		}

		List<Object[]> list = query.list();

		return list;

	}

	/**
	 * 
	 * @Title: sqlQueryUnResultObj @Description: 原生sql查询,查询单条记录 @param sql
	 *         原生sql @param parm 查询条件 @return Object[] 查询到的单个数据 @author
	 *         CHEHUANBO @throws
	 * 
	 */
	@Override
	public Object[] sqlQueryUnResultObj(String sql, Object... parm) {

		SQLQuery sqlQuery = this.getSQlQuery(sql);

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(sqlQuery, parm); // 设置sql参数
		}

		List<Object[]> objects = sqlQuery.list();

		Object[] obj = null;
		if (objects != null && objects.size() > 0) {
			obj = objects.get(0);
		}

		return obj;
	}

	/**
	 * 
	 * 获取查询记录数
	 * 
	 * @Title: sqlQueryGetCount 
	 * @param sql
	 * @param parm
	 * @return   记录数
	 * @author CHEHAUNBO
	 * 
	 */
	@Override
	public int sqlQueryGetCount(String sql, Object... parm) {

		SQLQuery sqlQuery = this.getSQlQuery(sql);

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(sqlQuery, parm); // 设置sql参数
		}

		int count = ((Number) sqlQuery.uniqueResult()).intValue();

		return count;

	}

	/**
	 * 
	 * @Title: updateSqlRow @Description: 执行修改SQL语句 @param sql 拼接SQL @param parm
	 *         不定参 @return int 受影响行数 @throws
	 * 
	 */
	@Override
	public int updateSqlRow(String sql, Object... parm) {
		int row = 0;
		try {
			SQLQuery query = this.getSQlQuery(sql);
			if (ToolUtil.isNotNullObj(parm)) {
				setParameters(query, parm);
			}
			row = query.executeUpdate();
		} catch (Exception e) {
			log.error("修改Hibernate对象出现异常！类：" + this.getClass() + " line:187", e);
		}
		return row;
	}

	/**
	 * 
	 * @Title: setParameters @Description: 设置参数 @return void @throws
	 * 
	 */
	public void setParameters(Query query, Object[] parmas) {

		if (query.getQueryString().indexOf("?") != -1) {

			for (int i = 0; i < parmas.length; i++) {
				if (parmas[i] instanceof Date) {
					query.setParameter(i, (Date) parmas[i]);
				} else {
					query.setParameter(i, parmas[i]);
				}
			}

		}

	}

	/**
	 * 
	 * @Title: getQuery @Description: 获取SQlQuery @param hql @return
	 *         Query @throws
	 * 
	 */
	protected SQLQuery getSQlQuery(String hql) {
		return this.getSession().createSQLQuery(hql);
	}

	public HibernateTemplate getTemplate() {
		return template;
	}

	public void setTemplate(HibernateTemplate template) {
		this.template = template;
	}

	/**
	 * 
	 * @Title: listSqlObj @Description: 原生sql查询 @param sql @param currentPage
	 * 当前页 @param pageSize 每页显示记录数 @param parm @return List<Object[]>
	 * 查询到的数据集合 @throws
	 */
	@Override
	public List<Object[]> sqlQueryListObj(String sql, boolean isCache, Object... parm) {

		SQLQuery query = this.getSQlQuery(sql);

		if (isCache) {
			query.setCacheable(true);
		}

		if (ToolUtil.isNotNullObj(parm)) {
			setParameters(query, parm); // 设置sql参数
		}
		List<Object[]> list = query.list();
		return list;
	}

	/**
	 * @Description: 获取查询条件
	 * @author fengshuonan
	 * @since 2.3.2
	 */
	public Criteria getCriteria() {
		return this.getSession().createCriteria(this.getGenericType());
	}

	/**
	 * 
	 * @Description:执行sql并把结果转化成自定义的bean
	 * @param sql 执行的sql语句
	 * @param beanClass 接受结果bean的class
	 * @author CHEHUANBO
	 * @since 2.4.0
	 * 
	 */
	public List<?> listSqlToCustomBean(String sql, Class<?> beanClass, Object... params) {

		SQLQuery query = this.getSQlQuery(sql);

		if (ToolUtil.isNotNullObj(params)) {
			setParameters(query, params); // 设置sql参数
		}

		if (beanClass != null) {
			query.setResultTransformer(Transformers.aliasToBean(beanClass));
		}

		return query.list();

	}

	/**
	 * @Description:执行sql并把结果转化成自定义的bean
	 * @param sql 执行的sql语句
	 * @param currentPage 分页查询：当前页
	 * @param pageSize 分页查询：每页显示数量
	 * @param beanClass 接受结果bean的class
	 * @param fieldList beanClass中需要做特殊处理的字段
	 * @author fengshuonan
	 * @since 2.4
	 */
	public List<?> listSqlToCustomBean(String sql, int currentPage, int pageSize, Class<?> beanClass,
			List<String> fieldList, Object... params) {

		SQLQuery query = this.getSQlQuery(sql);

		if (ToolUtil.isNotNullObj(params)) {
			setParameters(query, params); // 设置sql参数
		}

		if (pageSize != 0 && currentPage != 0) {
			query.setMaxResults(pageSize); // 每页查询多少条记录
			query.setFirstResult((currentPage - 1) * pageSize); // 从第几条记录开始查询
		}

		if (fieldList != null || fieldList.size() > 0) {
			AddScalar.addSclar(query, beanClass, fieldList);
		}

		if (beanClass != null) {
			query.setResultTransformer(Transformers.aliasToBean(beanClass));
		}

		return query.list();
	}
}
